package org.kdev.wtf.adapter;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.SeleniumException;

/**
 * Base HTML adapter
 */
public class BaseAdapter extends DefaultSelenium
{
   private final String WAIT_TIME; // ustawiana z appManager
   private String appContext;
   private String browserUrl;
   private String downloadPath;
   private static Class appManagerClass;
   private static Method appCheckPageErrorsMethod;

   public BaseAdapter(String serverHost, int serverPort, String browserStartCommand,
         String browserUrl, String appContext, String waitTime, Class aplicationClass,
         String downloadPath)

   {
      super(serverHost, serverPort, browserStartCommand, browserUrl);
      this.downloadPath = downloadPath;
      WAIT_TIME = (waitTime == null ? "30000" : waitTime);
      this.appContext = appContext;
      this.browserUrl = browserUrl;
      appManagerClass = aplicationClass;
      try
      {
         appCheckPageErrorsMethod = appManagerClass.getMethod("checkPageErrors");
      }
      catch (NoSuchMethodException e)
      {
         throw new SeleniumException(
               "There is no method 'checkPageErrors' in AppManagerClass ! \n", e);
      }
   }

   @Override
   public void type(String locator, String value)
   {
      // ignoruje argumenty == null
      // (przydatne gdy FormData jest tylko czesciowo wypelnione
      // - nie trzeba ustawaiac wszystkich parametrów)
      if (value == null)
         return;

      if (!this.isElementPresent(locator))
         throw new SeleniumException("Can not type to element where locator='" + locator + "'");
      super.type(locator, value);
   }

   public String getAppContext()
   {
      return this.appContext;
   }

   public String getBrowserUrl()
   {
      return this.browserUrl;
   }

   public String getDownloadPath()
   {
      return downloadPath;
   }

   /**
    * Open url using application context and wait for response. (appContext +
    * url)
    * 
    * @param url
    */
   public void openUrl(String url)
   {

      super.open(this.appContext + url);
      waitForPageToLoad();
      // sprawdz bledy na stronie (deleguje do menedzera aplikacji):
      try
      {
         appCheckPageErrorsMethod.invoke(null, (Object[]) null);
      }
      catch (InvocationTargetException e)
      {
         throw new SeleniumException(appManagerClass.getSimpleName() + ".checkPageErrors: "
               + e.getTargetException().getMessage());
      }
      catch (Exception e)
      {
         throw new SeleniumException("Blad wywolania checkPageErrors()!", e);
      }
   }

   public void openUrlWithoutErrorCheck(String url)
   {
      super.open(this.appContext + url);
      waitForPageToLoad();
   }

   public void typeInput(String inputName, String value)
   {
      String inputLocator = "xpath=//input[@name='" + inputName + "']";

      if (!this.isElementPresent(inputLocator))
         throw new SeleniumException("Can not type to input element where name='" + inputName + "'");
      this.type(inputLocator, value);
   }

   @Override
   public void typeKeys(String locator, String value)
   {
      if (!this.isElementPresent(locator))
         throw new SeleniumException("Can not type to element where locator='" + locator + "'");

      super.typeKeys(locator, value);
   }

   @Override
   public void click(String locator)
   {
      if (!this.isElementPresent(locator))
         throw new SeleniumException("Can not click on element where locator='" + locator + "'");

      super.click(locator);
   }

   public void clickAndWaitForPage(String locator)
   {
      this.click(locator);
      this.waitForPageToLoad();
   }

   public void clickButton(String buttonText)
   {
      String locator = "xpath=//button[text()='" + buttonText + "']";
      if (!this.isElementPresent(locator))
         throw new SeleniumException("Can not click on button where text='" + buttonText + "'");

      this.click(locator);
   }

   public void clickInput(String inputValue)
   {
      String locator = "xpath=//input[@value='" + inputValue + "']";
      if (!this.isElementPresent(locator))
         throw new SeleniumException("Can not click on input where value='" + inputValue + "'");

      this.click(locator);
   }

   public void clickLabel(String labelText)
   {
      String locator = "xpath=//span[text()='" + labelText + "']";
      if (!this.isElementPresent(locator))
         throw new SeleniumException("Can not click on label where text='" + labelText + "'");

      this.click(locator);
   }

   public void clickLink(String linkText)
   {
      this.click("link=" + linkText);
   }

   public void clickText(String divText)
   {
      this.click("xpath=//div[text()='" + divText + "']");
   }

   @Override
   public void select(String selectLocator, String optionLocator)
   {
      if (!this.isElementPresent(selectLocator))
         throw new SeleniumException("Can not select where locator='" + selectLocator + "'");

      super.select(selectLocator, optionLocator);
   }

   public void confirmAndWaitForPage()
   {
      this.getConfirmation();
      this.waitForPageToLoad();
   }

   public boolean isLinkPresent(String name)
   {
      return this.isElementPresent("link=" + name);
   }

   public void clickAndWaitForPopUp(String locator, String popUp)
   {
      this.click(locator);
      this.waitForPopUp(popUp, this.WAIT_TIME);
   }

   public void selectAndWaitForPage(String selectLocator, String optionLocator)
   {
      this.select(selectLocator, optionLocator);
      this.waitForPageToLoad();
   }

   public void selectWindowAndWaitForPage(String windowID)
   {
      this.selectWindow(windowID);
      this.waitForPageToLoad();
   }

   public void wait(String milis)
   {
      try
      {
         String condition = "selenium.isElementPresent('xxxlalalmidoxxx')";
         this.waitForCondition(condition, milis);
      }
      catch (Exception ex)
      {}
   }

   public void waitForElement(String locator)
   {
      String condition = "selenium.isElementPresent('" + locator.replace("'", "\\'") + "')";
      this.waitForCondition(condition);
   }

   public void waitForPopUp(String popUp)
   {
      this.waitForPopUp(popUp, this.WAIT_TIME);
   }

   public void waitForCondition(String condition)
   {
      this.waitForCondition(condition, this.WAIT_TIME);
   }

   public void waitForLabel(String label)
   {
      this.waitForElement("xpath=//span[text()='" + label + "']");
   }

   public void waitForPageToLoad()
   {
      super.waitForPageToLoad(this.WAIT_TIME);
   }

   public boolean isButtonPresent(String buttonText)
   {
      return this.isElementPresent("xpath=//button[text()='" + buttonText + "']");
   }

   public void highlightLabel(String labelText)
   {
      this.highlight("xpath=//span[text()='" + labelText + "']");
   }

   public void highlightText(String divText)
   {
      this.highlight("xpath=//div[text()='" + divText + "']");
   }
   
   /**
    * Click on Button (xpath=//div[@id='element']//button[text()='buttonText'])
    * 
    * @param element
    *        - HTML element contains buttonText
    * @param buttonText
    */
   public void clickButtonInElement(String element, String buttonText)
   {
      this.click("xpath=//div[@id='" + element + "']//button[text()='" + buttonText + "']");
   }
}